﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using System.Web;

using SharpBase.Web;

namespace SharpSNS
{
    /// <summary>
    /// Provides helper methods related to Request Signing
    /// </summary>
    public class RequestSigning
    {
        /// <summary>
        /// Generates a signature base string from the specified request web form
        /// </summary>
        /// <param name="method">Method for the request</param>
        /// <param name="reqForm">Web form</param>
        /// <returns>Returns a signature base string for the request</returns>
        public static string GenerateSignatureBaseString(string method, WebForm reqForm)
        {
            // Get the request URI
            string uri = reqForm.Uri.ToString();
            // Sort the parameters
            SortedDictionary<string, string> formParams = new SortedDictionary<string, string>();
            foreach (WebFormNameValuePair nvp in reqForm.FormParametersCollection)
                formParams.Add(nvp.Name, nvp.Value);
            // Generate the signature base string
            StringBuilder sbs = new StringBuilder();
            sbs.Append(method.ToUpper());
            sbs.Append("&");
            sbs.Append(Web.URLEncode(uri));
            sbs.Append("&");
            bool firstObj = true;
            foreach (KeyValuePair<string, string> kvp in formParams)
            {
                if (!firstObj)
                    sbs.Append(Web.URLEncode("&"));
                firstObj = false;
                sbs.AppendFormat("{0}{1}{2}",
                                    Web.URLEncode(Web.URLEncode(kvp.Key)),
                                    Web.URLEncode("="),
                                    Web.URLEncode(Web.URLEncode(kvp.Value)));
            }
            return sbs.ToString();
        }

        /// <summary>
        /// Generates a HMACSHA256 hash of the input using the specified key and 
        /// performs Base64 encoding on the result
        /// </summary>
        /// <param name="key">Key to use in hashing</param>
        /// <param name="input">Data to hash</param>
        /// <returns>Returns the Base64 encoded hash</returns>
        public static string HMACSHA256Base64(string key, string input)
        {
            HMACSHA256 hmc = new HMACSHA256(Encoding.UTF8.GetBytes(key));
            return Convert.ToBase64String(hmc.ComputeHash(Encoding.UTF8.GetBytes(input)));
        }
    }
}
